
/**
 * Twitter Helper
 */
function SOTwitterHelper(processFn) {
	this.authMethod = "basic";	// support basic auth method now
	this.user = "";
	this.pass = "";
	this.auth = "";	// base64 code for user:pass
	
	this.api = "https://twitter.com";	// default api
	
	// xAuth
	this.oauthConsumerKey = "pPObA0HvU4P2wNyNtEcgnA";
	this.oauthConsumerSecret = "o8Mxq6X8d5MjIZFMECSKAW8gHA1CPC00GJlXprYLs";
		
	this.success = false;	// short url state
	this.message = "";
	
	if (processFn) this.processFn = processFn;
}

SOTwitterHelper.prototype = {
	setBasicAuth: function(user, pass) {
		this.user = user;
		this.pass = pass;
		//this.auth = QuickTuiUtils.btoa(QuickTuiUtils.toUTF8Octets(this.user + ":" + this.pass));
	},
	
	setApi: function(api) {
		// remove the end "/"
		this.api = api.replace(/\/$/, "");
	},
	
	/**
	 * 作废
	 */
	_request: function(method, url, params, async, callback) {
		var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
					.createInstance(Components.interfaces.nsIXMLHttpRequest);
		req.mozBackgroundRequest = true; // FUCK, 如果没有这个，就会弹出个窗口让你输入用户名密码验证

		QuickTuiUtils.log("url: " + url);
		var scope = this;
		req.onload = function() { callback(req); };
		req.onerror = function() { scope._onError() };
				
		req.open(method, url, async);
		req.setRequestHeader("Authorization", 
					"Basic " + this.auth, 
					false);
		if ("POST" == method.toUpperCase()) {
			req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			req.setRequestHeader("Content-length", params.length);
			req.setRequestHeader("Connection", "close");
		}
		req.send(params);
	},

	_onerror: function() {
		this.success = false;
		this.message = "Short url false";
	},
	
	/**
	 * 已无效
	 */ 
	validateAccount: function() {
		var validated = false;
		var url = this.api + "/account/verify_credentials.json";

		var scope = this;
		this._request("GET", url, null, false, function(req) {
			switch(Number(req.status)) {
				case 401:
					validated = false;
					break;
				case 200:
					scope.success = true;
					validated = true;
					break;
				default:
					validated = false;
			}
 		});
		return validated;
	},
	
	/**
	 * xAuth 模式账号验证
	 */
	validateXAuthToken: function() {
		var validated = false;
	
		/*var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
					.createInstance(Components.interfaces.nsIXMLHttpRequest);
		req.mozBackgroundRequest = true; // FUCK, 如果没有这个，就会弹出个窗口让你输入用户名密码验证
		*/
		
		var req = QuickTuiUtils.initXMLHttpRequest();
		
		var url = this.api + "/oauth/access_token";
		
		QuickTuiUtils.log("validate xauth access token begin.....");
		
		var scope = this;
		req.onload = function() { 
			switch(Number(req.status)) {

				case 200:
					QuickTuiUtils.log("request status is 200");
					
					// 处理返回的req结果，并且将 oauth_token, oauth_token_secret 存入firefox配置中
					validated = scope.processOAuthToken(scope, req);
					
					break;
				default:
					scope.success = false;
					scope.message = "An error occurred during account validation[Error Code]: " + req.status;

					validated = false;
			}
		};
		req.onerror = function() { 
			scope.success = false;
			scope.message = "An error occurred during account validation[Error Code]: " + req.status;
		};
		
		var nonce = QuickTuiUtils.nonce(8);
		var timestamp = this.getTimestamp();
		
		// Get oauth signature
		var baseString = this.getTokenReqBaseString(url, nonce, timestamp);
		QuickTuiUtils.log("base string: " + baseString);
		
		var oauthSignature = this.sign(baseString, "");
		
		var params = ""
			  + "x_auth_mode=client_auth"
			  + "&x_auth_username=" + this.encodeUri(this.user)
			  + "&x_auth_password=" + this.encodeUri(this.pass)
		QuickTuiUtils.log("params: " + params);

		req.open("POST", url, false);
      		
		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		/*req.setRequestHeader("Content-length", params.length);
		req.setRequestHeader("Connection", "close");
		*/
		var authHeader = "OAuth ";
		authHeader += "oauth_consumer_key=\"" + this.encodeUri(this.oauthConsumerKey) + "\",";
		authHeader += "oauth_signature=\"" + this.encodeUri(oauthSignature) + "\",";
		//authHeader += "oauth_token=\"\"";
		authHeader += "oauth_nonce=\"" + this.encodeUri(nonce) + "\",";
		authHeader += "oauth_signature_method=\"HMAC-SHA1\",";
		authHeader += "oauth_timestamp=\"" + timestamp + "\",";
		authHeader += "oauth_version=\"1.0\"";
		
		req.setRequestHeader("Authorization", 
					authHeader, 
					false);
		QuickTuiUtils.log("auth: " + authHeader);
		
		req.send(params);
		
		return validated;
	},
	
	sign: function(baseString, tokenSecret) {
		var signSecretKey = this.encodeUri(this.oauthConsumerSecret) + "&" + this.encodeUri(tokenSecret);
		QuickTuiUtils.log("oauthSignature source: " + signSecretKey);
		
		
		b64pad = '=';
		var oauthSignature = b64_hmac_sha1(signSecretKey, baseString);
		QuickTuiUtils.log("oauthSignature: " + oauthSignature);
		
		return oauthSignature;
	},
	
	processOAuthToken: function(scope, req) {
		
		var txt = req.responseText;
		QuickTuiUtils.log(txt);
		
		if (txt == null || txt == "") {
			scope.success = false;
			scope.message = "The request token is null";
			return false;
		}
		
		var items = txt.split("&");
		
		for (var i in items) {
			QuickTuiUtils.log(items[i]);
			var item = items[i];
			if (item.indexOf("oauth_token=") != -1) {
				var token = item.slice(item.indexOf("=") + 1);
				QuickTuiUtils.prefs.setCharPref("oauthToken", token);
			}
			if (item.indexOf("oauth_token_secret=") != -1) {
				var tokenSecret = item.slice(item.indexOf("=") + 1);
				QuickTuiUtils.prefs.setCharPref("oauthTokenSecret", tokenSecret);
			}
		}
		
		return true;
	},
	
	updateState: function(text, beginFn, overFn) {
		var result = 0;
		
		var oauthToken = QuickTuiUtils.prefs.getCharPref("oauthToken");
		var oauthTokenSecret = QuickTuiUtils.prefs.getCharPref("oauthTokenSecret");
		
		if (!oauthToken || !oauthTokenSecret) {
			alert("Please config your twitter account first!");
			return;
		}
		
		var url = this.api + "/statuses/update.json";
		// 判断下是否使用了自定义api，如果没有，则使用twitter自己提供的地址，否则用api的
		if (this.api.indexOf("twitter.com") != -1) {
			url = "http://api.twitter.com/1/statuses/update.json";
		}

		var scope = this;
		if (beginFn) beginFn();

		var req = QuickTuiUtils.initXMLHttpRequest();
		
		QuickTuiUtils.log("update tweet begin.....");
		
		var scope = this;
		req.onload = function() { 
			switch(Number(req.status)) {

				case 200:
					QuickTuiUtils.log("request status is 200");
					
					result = 200;
					scope.success = true;
					scope.processFn(req);
					
					break;
				default:
					scope.success = false;
					scope.message = "An error occurred during update tweet[Error Code]: " + req.status;

					QuickTuiUtils.log("req.responseText error: " + req.responseText);
					result = 0;
			}
		};
		req.onerror = function() { 
			scope.success = false;
			scope.message = "An error occurred during update tweet [Error Code]: " + req.status;
		};
		
		var nonce = QuickTuiUtils.nonce(8);
		var timestamp = this.getTimestamp();
		
		// Get oauth signature
		var baseString = this.getUpdateBaseString(url, nonce, timestamp, oauthToken, text);
		QuickTuiUtils.log("base string: " + baseString);
		
		
		var oauthSignature = this.sign(baseString, oauthTokenSecret);

		req.open("POST", url, false);

		req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		var authHeader = "OAuth ";
		authHeader += "oauth_consumer_key=\"" + this.encodeUri(this.oauthConsumerKey) + "\",";
		authHeader += "oauth_signature=\"" + this.encodeUri(oauthSignature) + "\",";
		authHeader += "oauth_token=\"" + this.encodeUri(oauthToken) + "\",";
		authHeader += "oauth_nonce=\"" + this.encodeUri(nonce) + "\",";
		authHeader += "oauth_signature_method=\"HMAC-SHA1\",";
		authHeader += "oauth_timestamp=\"" + timestamp + "\",";
		authHeader += "oauth_version=\"1.0\"";
		//authHeader += ",status=" + this.encodeUri(text);
		
		req.setRequestHeader("Authorization", 
					authHeader, 
					false);
		QuickTuiUtils.log("auth: " + authHeader);
		
		req.send("status=" + this.encodeUri(text));
		
		if (overFn) overFn();
		
		return result;
	},
	
	/////////////////////////////////////////////////////////////////////////
	// xAuth Mehtod
	
	getTimestamp: function() {
		var t = new Date().getTime();
		return Math.floor(t / 1000);
	},
	
	encodeUri: function(s) {
		if (s == null) {
            return "";
        }
        
        var ss = encodeURIComponent(s);
        // Now replace the values which encodeURIComponent doesn't do
        // encodeURIComponent ignores: - _ . ! ~ * ' ( )
        // OAuth dictates the only ones you can ignore are: - _ . ~
        // Source: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURIComponent
        ss = ss.replace(/\!/g, "%21");
        ss = ss.replace(/\*/g, "%2A");
        ss = ss.replace(/\'/g, "%27");
        ss = ss.replace(/\(/g, "%28");
        ss = ss.replace(/\)/g, "%29");
        return ss;
	},
	
	getTokenReqBaseString: function(url, nonce, timestamp) {

		var baseUri = this.encodeUri(url);
		
		var params = "";
		params += "oauth_consumer_key=" + this.encodeUri(this.oauthConsumerKey);
		params += "&oauth_nonce=" + this.encodeUri(nonce);
		params += "&oauth_signature_method=HMAC-SHA1";
		params += "&oauth_timestamp=" + timestamp;
		params += "&oauth_version=1.0";
		params += "&x_auth_mode=client_auth";
		params += "&x_auth_password=" + this.encodeUri(this.pass);
		params += "&x_auth_username=" + this.encodeUri(this.user);
		
		return "POST&" + baseUri + "&" + this.encodeUri(params);
	},
	
	getUpdateBaseString: function(url, nonce, timestamp, oauthToken, text) {

		var baseUri = this.encodeUri(url);
		
		var params = "";
		params += "oauth_consumer_key=" + this.encodeUri(this.oauthConsumerKey);
		params += "&oauth_nonce=" + this.encodeUri(nonce);
		params += "&oauth_signature_method=HMAC-SHA1";
		params += "&oauth_timestamp=" + timestamp;
		params += "&oauth_token=" + this.encodeUri(oauthToken);
		params += "&oauth_version=1.0";
		params += "&status=" + this.encodeUri(text);
		
		return "POST&" + baseUri + "&" + this.encodeUri(params);
	},

	/////////////////////////////////////////////////////////////////////////
	
	toString: function() {
		return "[" + this.user + ", " + this.pass + ", " + this.auth
				+ "]";
	}
}